{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# blob printing\n",
    "\n",
    "*<<< check out other demo models [here](https://github.com/FullControlXYZ/fullcontrol/tree/master/models/README.md) >>>*\n",
    "  \n",
    "run all cells in this notebook, or press shift+enter to run each cell sequentially \n",
    "\n",
    "if you change one of the code cells, make sure you run it and all subsequent cells again (in order)\n",
    "\n",
    "*this document is a jupyter notebook - if they're new to you, check out how they work: [link](https://www.google.com/search?q=ipynb+tutorial), [link](https://jupyter.org/try-jupyter/retro/notebooks/?path=notebooks/Intro.ipynb), [link](https://colab.research.google.com/)*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import fullcontrol as fc\n",
    "from math import tau"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# printer/gcode parameters\n",
    "\n",
    "design_name = 'blobs'\n",
    "nozzle_temp = 210\n",
    "bed_temp = 40\n",
    "fan_percent = 100\n",
    "printer_name='prusa_i3' # generic / ultimaker2plus / prusa_i3 / ender_3 / cr_10 / bambulab_x1 / toolchanger_T0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# design parameters\n",
    "\n",
    "tube_radius = 10  # overall radius of the tubular structure formed of lots of blobs\n",
    "blob_size = 1.6  # diameter of blobs (in XY plane)\n",
    "# percentage overlap between neighbouring blobs (in XY plane). this value is for the denser 'top/bottom' layers - for middle less-dense layers, the blobs are twice as far apart\n",
    "bloc_overlap_percent = 33\n",
    "layers = 10\n",
    "dense_layers = 2  # this is the number of layers at the top and bottom that have double the number of blobs. other layers have fewer blobs with a small gap in between\n",
    "extrusion_speed = 100  # speed of extrusion set in gcode for extrusion-only G1 commands. The units of this speed depend on your printer but are likely mm/min or mm3/min\n",
    "centre_x, centre_y = 50, 50"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# generate the design (make sure you've run the above cells before running this cell)\n",
    "\n",
    "\n",
    "blob_height = blob_size/2\n",
    "blob_spacing = blob_size*(1-bloc_overlap_percent/100)\n",
    "blob_vol = blob_height*blob_size**2\n",
    "initial_z = 0.95*blob_height\n",
    "\n",
    "\n",
    "def move_and_blob(steps: list, point: fc.Point, volume: float, extrusion_speed: float) -> list:\n",
    "    steps.extend([point, fc.StationaryExtrusion(\n",
    "        volume=volume, speed=extrusion_speed), fc.PlotAnnotation(label='')])\n",
    "\n",
    "\n",
    "blobs_per_layer = int(tau*tube_radius/blob_spacing)\n",
    "if blobs_per_layer % 2 != 0:\n",
    "    # number of blobs increased by 1 to achieve an even number of blocks per layer\n",
    "    blobs_per_layer += 1\n",
    "angle_between_blobs = tau/blobs_per_layer\n",
    "\n",
    "steps = []\n",
    "\n",
    "# add primer line to get flow going and get attachment to the print bed:\n",
    "steps.extend([fc.Extruder(on=True), fc.Point(x=tube_radius+20*blob_spacing, y=0, z=0), fc.Printer(print_speed=100),\n",
    "             fc.ExtrusionGeometry(width=blob_size, height=blob_height), fc.Point(x=tube_radius+10*blob_spacing), fc.Extruder(on=False)])\n",
    "\n",
    "# add primer of 10 blobs to get into steady-state conditions:\n",
    "primer_blob_pts = fc.segmented_line(fc.Point(x=tube_radius+10*blob_spacing, y=0, z=0), fc.Point(x=tube_radius, y=0, z=0), 10)\n",
    "for blob_pt in primer_blob_pts[1:-1]: move_and_blob(steps, blob_pt, blob_vol, extrusion_speed)\n",
    "\n",
    "# print all the blobs:\n",
    "for layer in range(layers):\n",
    "    for blob in range(blobs_per_layer):\n",
    "        if (layer < dense_layers or layer >= layers-dense_layers) or blob % 2 == 0:\n",
    "            move_and_blob(steps, fc.polar_to_point(centre=fc.Point(x=0, y=0, z=layer *\n",
    "                          blob_height), radius=tube_radius, angle=angle_between_blobs*blob), blob_vol, extrusion_speed)\n",
    "    # move directly over the top of the first point so the nozzle moves directly up in Z to begin the second layer\n",
    "    steps.append(fc.Point(x=0+tube_radius, y=0))\n",
    "\n",
    "# offset the whole procedure. z dictates the gap between the nozzle and the bed for the first layer, assuming the model was designed with a first layer z-position of 0\n",
    "model_offset = fc.Vector(x=centre_x, y=centre_y, z=initial_z)\n",
    "steps = fc.move(steps, model_offset)\n",
    "\n",
    "steps.append(fc.PlotAnnotation(point=fc.Point(x=centre_x, y=centre_y, z=blob_height*layers*2),\n",
    "             label=f'Nodes in this preview show where blobs are deposited, but do not represent the size of blobs'))\n",
    "steps.append(fc.PlotAnnotation(point=fc.Point(x=centre_x, y=centre_y, z=blob_height*layers*1.5),\n",
    "             label=f'For this blob volume ({blob_vol:.1f} mm3) a good blob extrusion speed may take about {blob_vol/4:.1f}-{blob_vol/2:.1f} seconds per blob'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# preview the design\n",
    "\n",
    "fc.transform(steps, 'plot', fc.PlotControls(style='line'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# generate and save gcode\n",
    "\n",
    "gcode_controls = fc.GcodeControls(\n",
    "    printer_name=printer_name,\n",
    "    save_as=design_name,\n",
    "    initialization_data={\n",
    "        'primer': 'travel',\n",
    "        'nozzle_temp': nozzle_temp,\n",
    "        'bed_temp': bed_temp,\n",
    "        'fan_percent': fan_percent})\n",
    "gcode = fc.transform(steps, 'gcode', gcode_controls)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### please tell us what you're doing with FullControl!\n",
    "\n",
    "- tag FullControlXYZ on social media ([twitter](https://twitter.com/FullControlXYZ), [instagram](https://www.instagram.com/fullcontrolxyz/), [linkedin](https://www.linkedin.com/in/andrew-gleadall-068587119/), [tiktok](https://www.tiktok.com/@fullcontrolxyz))\n",
    "- email [info@fullcontrol.xyz](mailto:info@fullcontrol.xyz)\n",
    "- post on the [subreddit](https://reddit.com/r/fullcontrol)\n",
    "- post in the [github discussions or issues tabs](https://github.com/FullControlXYZ/fullcontrol/issues)\n",
    "\n",
    "in publications, please cite the original FullControl paper and the github repo for the new python version:\n",
    "\n",
    "- Gleadall, A. (2021). FullControl GCode Designer: open-source software for unconstrained design in additive manufacturing. Additive Manufacturing, 46, 102109. \n",
    "- Gleadall, A. and Leas, D. (2023). FullControl [electronic resource: python source code]. available at: https://github.com/FullControlXYZ/fullcontrol"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.3"
  },
  "vscode": {
   "interpreter": {
    "hash": "2b13a99eb0d91dd901c683fa32c6210ac0c6779bab056ce7c570b3b366dfe237"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
